/**
 * 给定A/B两个数组，再给定Q个询问，每次问：
 *  a b x y
 * 问A[a...b]与B[x...y]在不计顺序的情况下是否可以一一对应
 * 
 * 假设长度为5，且取值范围也在[1, 5]，可以把数组按照10的幂进行映射
 * 即，假设A = [2, 3, 5, 1, 4]，则将A映射为 [1E2, 1E3, 1E5, 1E1, 1E4]
 * 这样的话，如果A[a...b]与B[x...y]的和相等，则说明它们可以一一对应，否则不行。
 * 
 * 选用双哈希自然溢出。
 * 区间和用线段树。树状数组应该也行。
 * O(NlogN+QlogN)
 */
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;

using llt = long long;
using vi = vector<int>;
using vll = vector<llt>;
using pii = pair<int, int>;
using pll = pair<llt, llt>;

using _t = array<llt, 2>;
_t Seeds {10LL, 13313LL};
vector<_t> Pow;

bool operator == (const _t & a, const _t & b) {
    for(int i=0;i<a.size();++i){
        if(a[i] != b[i]) return false;
    }
    return true;
}

const _t operator + (const _t & a, const _t & b) {
    _t ans;
    for(int i=0;i<a.size();++i){
        ans[i] = (a[i] + b[i]);
    }
    return ans;
}

const _t operator * (const _t & a, const _t & b) {
    _t ans;
    for(int i=0;i<a.size();++i){
        ans[i] = a[i] * b[i];
    }
    return ans;
}

const _t operator * (const _t & a, llt b) {
    _t ans;
    for(int i=0;i<a.size();++i){
        ans[i] = a[i] * b;
    }
    return ans;
}


struct SegTree{ // 线段树带延迟

using llt = long long;

int N;

using value_type = _t;
vector<value_type> data; // 线段树

// using lazy_type = llt;
// vector<lazy_type> lazy; // 延迟标记

/// 从下往上计算信息，要变动
value_type _up_(const value_type & ls, const value_type & rs) {
    return ls + rs;
}

/// 初始化，清零，不用动
void init(int n) {
    data.assign((N = n) + 1 << 2, value_zero());
}

/// 这个函数不用动
value_type query(int a, int b){
    return _query(1, 1, N, a, b);
}

/// 这个函数不用动
void build() {
    _build(1, 1, N);
}

/// 几乎不用动
value_type _query(int t, int s, int e, int a, int b) {
    if(a <= s and e <= b) {
        return data[t];
    }

    int mid = (s + e) >> 1;
    value_type ans = value_zero(); // 如果求最值，这里不能用zero
    if(a <= mid) ans = _up_(ans, _query(lson(t), s, mid, a, b));
    if(mid < b) ans = _up_(ans, _query(rson(t), mid + 1, e, a, b));
    return ans;
}


/// 这个函数不用动
void _pushUp(int t) {
    data[t] = _up_(data[lson(t)], data[rson(t)]);
}

/// 几乎不用动
void _build(int t, int s, int e) {
    if(s == e) {
        int x; cin >> x;
        data[t] = Pow[x] * (llt)x;
        return; 
    }
    int mid = (s + e) >> 1;
    _build(lson(t), s, mid);
    _build(rson(t), mid + 1, e);
    _pushUp(t);
}

/// 辅助函数，视线段树信息类型而变动
static const value_type & value_zero() {
    static const value_type VALUE0 = {0LL, 0LL};
    return VALUE0;
}

/// 这两个函数不用变动
static int lson(int x) {return x << 1;}
static int rson(int x) {return lson(x) | 1;}


};


int Q;
int N;

SegTree A, B;

void work(){
    cin >> N >> Q;
    Pow.assign(N + 1, {});
    Pow[0] = {1LL, 1LL};
    for(int i=1,n=Pow.size();i<n;++i){
        Pow[i] = Pow[i - 1] * Seeds;
    }

    A.init(N); A.build();
    B.init(N); B.build();

    for(int a,b,x,y,q=1;q<=Q;++q){
        cin >> a >> b >> x >> y;
        auto u = A.query(a, b);
        auto v = B.query(x, y);
        cout << (u == v ? "Yes\n" : "No\n");
    }
    return;
}


int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);	
    int nofkase = 1;
	// cin >> nofkase;
	while(nofkase--) work();
	return 0;
}